package com.metal.silver.util;

import com.alibaba.fastjson.JSONObject;
import com.metal.silver.exception.BusinessException;
import com.metal.silver.exception.ResponseCode;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName MongoDBUtil
 * @Description
 * @Author liukun
 * @Date 2022/9/2 11:19
 */
@Slf4j
@Component
public class MongoDBUtil {

    static MongoClient client = null;

    static String mongoHost;
    static int mongoPort;
    static boolean usePassword;
    static String mongoUser;
    static String mongoPassword;
    static String db = "silver";

    @Value("${mongodb.mongoHost:'未设置'}")
    public void setMongoHost(String mongoHost) {
        this.mongoHost = mongoHost;
    }
    @Value("${mongodb.mongoPort:27017}")
    public void setMongoPort(int mongoPort) {
        this.mongoPort = mongoPort;
    }
    @Value("${mongodb.usePassword:false}")
    public void setUsePassword(boolean usePassword) {
        this.usePassword = usePassword;
    }
    @Value("${mongodb.mongoUser:''}")
    public void setMongoUser(String mongoUser) {
        this.mongoUser = mongoUser;
    }
    @Value("${mongodb.mongoPassword:''}")
    public void setMongoPassword(String mongoPassword) {
        this.mongoPassword = mongoPassword;
    }

    private MongoDBUtil() {
    }

    private static MongoClient getConnection() {
        if (client == null) {
            MongoClientURI uri;
            if (usePassword) {
                uri = new MongoClientURI(String.format("mongodb://%s:%s@%s:%d/%s", mongoUser, mongoPassword, mongoHost, mongoPort, db));
            }
            else {
                uri = new MongoClientURI(String.format("mongodb://%s:%d/%s", mongoHost, mongoPort, db));
            }
            client = new MongoClient(uri);
        }
        return client;
    }

    private static MongoDatabase getDatabase(String db) {
        MongoDatabase database = getConnection().getDatabase(db);
        return database;
    }

    public static MongoCollection<Document> getCollection(String collection) {
        MongoCollection<Document> doc = getDatabase(db).getCollection(collection);
        return doc;
    }

    public static MongoCollection<Document> getDocument(String document) {
        MongoCollection<Document> doc = getDatabase(db).getCollection(document);
        return doc;
    }

    public static JSONObject queryOneByUuid(String collection, String uuid) {
        JSONObject queryJsonObj = new JSONObject();
        queryJsonObj.put("uuid", uuid);
        Document queryDoc = Document.parse(queryJsonObj.toJSONString());
        FindIterable<Document> documents = getCollection(collection).find(queryDoc);
        return resultOne(documents);
    }

    /**
     * 根据mongodb的 _id 字段进行选择性更新：dataJson中存在的key，会被更新。db中有，但是dataJson中没有的key，不会被更新。
     * @param uuid
     * @param dataJson
     */
    public static void updateSelectiveByUuid(String doc, String uuid, String dataJson) {
        JSONObject idJson = new JSONObject();
        idJson.put("uuid", uuid);
        Document doc1 = Document.parse(idJson.toJSONString());
        Document doc2 = new Document("$set", Document.parse(dataJson));
        UpdateOptions up = new UpdateOptions();
        up.upsert(false);
        UpdateResult a = getCollection(doc).updateOne(doc1, doc2, up);
        log.info("根据uuid更新结果:{}", a);
    }

    public static void main(String[] args) {

        /*MongoClientURI uri = new MongoClientURI(String.format("mongodb://%s:%s@%s:%d/zd", "zd", "zdadmin123", "172.18.2.52", 27017));
        client = new MongoClient(uri);
        MongoCollection<Document> collection = client.getDatabase("zd").getCollection("customer");

        JSONObject jsonObject = JSONObject.parseObject("{\"hello\":\"world\"}");
        jsonObject.put("_id", "123");
        Document insertDoc = Document.parse(jsonObject.toJSONString());

        collection.insertOne(insertDoc);*/


        // 插入数据
        /*MongoDBUtil.saveDocument("zd",
                "customer",
                "{\"customer_number\":\"CU20220706141459123333\",\"companyName\":\"北京百度网讯科技有限公司\",\"creditCode\":\"91110000802100433B\",\"legalPersonName\":\"梁志祥\",\"legalPersonMobile\":\"13222222222\"}",
                "customer_number");

        FindIterable<Document> documents = MongoDBUtil.find("zd", "customer", "{\"customer_number\": \"CU20220706141459123333\"}");
        for (Document doc : documents) {
            System.out.println(doc);
        }*/

        /*updateDocument("zd",
                "customer",
                "{\"customer_number\":\"CU20220706141459123333\"}",
                "{\"companyName\":\"111\", \"creditCode\":\"222\"}"
                );

        FindIterable<Document> documents = MongoDBUtil.find("zd", "customer", "{\"customer_number\": \"CU20220706141459123333\"}");
        for (Document doc : documents) {
            System.out.println(doc);
        }*/

        // 时间区间查询
        /*BasicDBObject query= new BasicDBObject();
        BasicDBList timeList = new BasicDBList();
        timeList.add(new BasicDBObject("add_time", new BasicDBObject("$gte", "2022-09-04").append("$lte", "2022-09-05")));
        query.put("$and", timeList);
        FindIterable<Document> documents = MongoDBUtil.getDocument("zd", "customer")
                .find(query);
        List<JSONObject> resultList = MongoDBUtil.resultList(documents);
        resultList.stream().forEach(e -> {
            System.out.println(e);
        });*/

        /*BasicDBObject query= new BasicDBObject();
        JSONObject timeCondition = new JSONObject();
        timeCondition.put("$gt", "2022-09-04");
        timeCondition.put("$lt", "2022-09-05");
        query.put("add_time", timeCondition);
        FindIterable<Document> documents = MongoDBUtil.getDocument("zd", "customer")
                .find(query);
        List<JSONObject> resultList = MongoDBUtil.resultList(documents);
        resultList.stream().forEach(e -> {
            System.out.println(e);
        });*/


//        JSONObject doc = findOne("zd", "customer", "{\"name\": \"貂蝉\"}"    );
//        System.out.println(doc);
    }


    /**
     * 仅仅是将 FindIterable<Document> documents 转换为 List<JSONObject>
     * @param documents
     * @return
     */
    public static List<JSONObject> resultList(FindIterable<Document> documents) {
        if (documents == null) {
            return null;
        }
        else {
            List<JSONObject> resultList = new ArrayList<>();
            for (Document doc : documents) {
                resultList.add((JSONObject) JSONObject.toJSON(doc));
            }
            return resultList;
        }
    }
    public static JSONObject resultOne(FindIterable<Document> documents) {
        if (documents != null) {
            int count = 0;
            JSONObject jsonObj = null;
            for (Document tmpDoc: documents) {
                jsonObj = (JSONObject) JSONObject.toJSON(tmpDoc);
                count ++;
            }
            if (count > 1) {
                throw new BusinessException(ResponseCode.ONE_LINE_EXPECTED, "预期mongo中一条数据，但查出多条");
            }
            return jsonObj;
        }
        else {
            return null;
        }
    }
}
